﻿using ChangeWifiWebApi.Models;
using SimpleWifi;
using System;
using System.Linq;
using System.Runtime.Caching;
using System.Threading.Tasks;
using Unosquare.Labs.EmbedIO;
using Unosquare.Labs.EmbedIO.Constants;
using Unosquare.Labs.EmbedIO.Modules;
using Unosquare.Net;
using Unosquare.Swan;

namespace ChangeWifiWebApi
{
  public class WifiController : WebApiController
  {
    private static readonly ObjectCache _Cache = MemoryCache.Default;

    [WebApiHandler(HttpVerbs.Get, "/api/wifi")]
    public bool GetWifi(WebServer server, HttpListenerContext context)
    {
      try
      {
        var wifiList = from dd in GetWifiListByCache()
                       select new WifiPointInfo
                       {
                         SSID = dd.Name,
                         SignalStrength = (int)dd.SignalStrength
                       };
        return context.JsonResponse(wifiList);
      }
      catch (Exception ex)
      {
        return HandleError(context, ex, (int)System.Net.HttpStatusCode.InternalServerError);
      }
    }

    [WebApiHandler(HttpVerbs.Post, "/api/wifi")]
    public async Task<bool> PostChangeWifiAsync(WebServer server, HttpListenerContext context)
    {
      var wl = context.ParseJson<WifiLoginInfo>();
      var wifiList = GetWifiListByCache();
      var ap = wifiList.Where(ww => ww.Name == wl.SSID).FirstOrDefault();
      if (null == ap)
      {
        return await context.HtmlResponseAsync("", System.Net.HttpStatusCode.NotFound);
      }
      else
      {
        Console.WriteLine($"Start change wifi. ssid={ap.Name}, pwd={wl.Password}");
        AuthRequest authRequest = new AuthRequest(ap)
        {
          Password = wl.Password
        };
        ap.ConnectAsync(authRequest, true);
        Console.WriteLine("Finish change wifi.");
        return await context.StringResponseAsync("");
      }
    }

    private AccessPoint[] GetWifiListByCache()
    {
      var accessPoints = _Cache["accessPoints"] as AccessPoint[];
      if (null == accessPoints)
      {
        var wifi = new Wifi();
        accessPoints = wifi.GetAccessPoints().OrderByDescending(ap => ap.SignalStrength).ToArray();
        CacheItemPolicy policy = new CacheItemPolicy();
        policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(5);
        _Cache.Set("accessPoints", accessPoints, policy);
      }
      return accessPoints;
    }

    protected bool HandleError(HttpListenerContext context, Exception ex, int statusCode = 500)
    {
      var errorResponse = new
      {
        Title = "Unexpected Error",
        ErrorCode = ex.GetType().Name,
        Description = ex.ExceptionMessage(),
      };
      context.Response.StatusCode = statusCode;
      return context.JsonResponse(errorResponse);
    }
  }
}